#region

using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Vin.Tool.AspNetCore.Service;
using Vin.Tool.Core.RandomCategory;

#endregion

namespace Vin.Extension.Captcha.Service.Implement.GenerateCaptcha;

public class VinBaseGenerateCaptchaService : VinBaseService
{
    /// <summary>
    /// 生成验证码
    /// </summary>
    /// <param name="width">宽</param>
    /// <param name="height">高</param>
    /// <param name="text">文本</param>
    /// <param name="font">字体</param>
    /// <param name="fontSize">字体大小</param>
    /// <param name="format">输出格式</param>
    /// <param name="lineCount">干扰线数量</param>
    /// <param name="angleMin">角度最小值</param>
    /// <param name="angleMax">角度最大值</param>
    /// <param name="bg">背景颜色</param>
    /// <returns>base64</returns>
    public string CreateImageBase64(int width, int height, char[] text, Font font, int fontSize,
        IImageFormat format, int lineCount = 6, int angleMin = -70, int angleMax = 70, Color? bg = null)
    {
        bg ??= Color.White;
        using var image = new Image<Rgba32>(width, height);
        image.Mutate(ctx =>
        {
            // 绘制背景
            ctx.Fill(bg.Value);
            // 绘制验证码
            DrawChars(ctx, height / 2 - fontSize / 2, text, font, fontSize, angleMin, angleMax);
            // 绘制干扰线
            DrawInterferenceLines(ctx, width, height, lineCount);
        });

        return image.ToBase64String(format);
    }

    public void DrawChar(IImageProcessingContext ctx, char text, DrawingOptions options, Font font, Color color,
        PointF point)
    {
        ctx.DrawText(options, text.ToString(), font, color, point);
    }

    public void DrawChars(IImageProcessingContext ctx, int y, char[] text, Font font, int fontSize,
        int angleMin = -70, int angleMax = 70)
    {
        for (int i = 0; i < text.Length; i++)
        {
            var angle = RandomTool.RandomInt(angleMin, angleMax);
            var point = new PointF(i * fontSize + fontSize, y);
            var color = Color.Parse(RandomColorTool.RandomColor());
            var options = new DrawingOptions
            {
                Transform = Matrix3x2Extensions.CreateRotationDegrees(angle, point)
            };
            DrawChar(ctx, text[i], options, font, color, point);
        }
    }

    public void DrawInterferenceLines(IImageProcessingContext ctx, int width, int height, int count)
    {
        for (int i = 0; i < count; i++)
        {
            var p1 = new PointF(RandomTool.RandomInt(0, width), RandomTool.RandomInt(0, height));
            var p2 = new PointF(RandomTool.RandomInt(0, width), RandomTool.RandomInt(0, height));
            ctx.DrawLine(Color.Parse(RandomColorTool.RandomColor()), 1, p1, p2);
        }
    }
}